package com.atwulidun.strategy21;

public abstract class Duck {
    // 将三种行为接口聚合进来
    protected Fly fly;
    protected Quack quack;
    protected Swim swim;

    // 定义三种方法，子类需要用到哪种行为，那就把相应的行为对象传进来即可
    // 若某种行为对象为null，那么调用该种行为方法相当于调用一个空方法
    protected void fly() {
        if (fly != null) {
            fly.fly();
        }
    }

    protected void quack() {
        if (quack != null) {
            quack.quack();
        }
    }

    protected void swim() {
        if (swim != null) {
            swim.swim();
        }
    }

    protected abstract void display();

    // 为了能够动态地改变鸭子的行为，这里还应该提供setter方法

    public void setFly(Fly fly) {
        this.fly = fly;
    }

    public void setQuack(Quack quack) {
        this.quack = quack;
    }

    public void setSwim(Swim swim) {
        this.swim = swim;
    }
}

// 具体的鸭子类
class WildDuck extends Duck {
    // 野鸭要fly和quack两种行为，那么构造器就把这两种行为对象传进来即可
    public WildDuck() {
        fly = new HighFly();
        quack = new GaGaQuack();
    }

    @Override
    protected void display() {
        System.out.println("这里是野鸭：");
        fly.fly();
        quack.quack();
    }
}

class PekingDuck extends Duck {
    // 北京鸭需要fly、quack和swim三种行为，那么构造器就把这三种行为对象传进来即可
    public PekingDuck() {
        fly = new LowFly();
        quack = new GuGuQuack();
        swim = new SlowSwim();
    }

    @Override
    protected void display() {
        System.out.println("这里是北京鸭：");
        fly.fly();
        quack.quack();
        swim.swim();
    }
}

class ToyDuck extends Duck {
    // 玩具呀需要fly一种行为，构造器把该行为对象传进来即可
    public ToyDuck() {
        fly = new NoFly();
    }

    @Override
    protected void display() {
        System.out.println("这里是玩具鸭：");
        fly.fly();
    }
}